package agenda;

import lib.api.AgendaTDA;
import lib.api.ColaPrioridadTDA;
import lib.api.ConjuntoIntTDA;
import lib.api.ConjuntoStringTDA;
import lib.api.DiccionarioSimpleTDA;
import lib.impl.ColaPrioridadImpl;
import lib.impl.ConjuntoIntImpl;
import lib.impl.ConjuntoStringImpl;
import lib.impl.DiccionarioSimpleImpl;

public class MetodosExternos {
	
	/* EliminarEvento: dad una agenda incializada, y un evento, 
	 * saca este evento de todas las fechas que lo contengan.
	 */
    public static void EliminarEvento(AgendaTDA a, String evento) {
    	ConjuntoIntTDA auxfechas = new ConjuntoIntImpl();
    	ConjuntoStringTDA auxeventos = new ConjuntoStringImpl();
    	int fecha;

    	if( a != null ){
    		auxfechas = a.FechasAgendadas();
    		while( !auxfechas.ConjuntoVacio()){
    			fecha = auxfechas.Elegir();
        		auxeventos = a.EventosFecha(fecha);
    			if( auxeventos.Pertenece(evento) )
    				a.CancelarEvento(fecha, evento);
    			auxfechas.Sacar(fecha);
    		}
    	}
    }
	
	/* FechasConEvento: dada una agenda incializada, y un evento 
	 * devuelve el conjunto de fechas en las el evento esta agendado.
	 */
    public static ConjuntoIntTDA FechasConEvento(AgendaTDA a, String evento) {
    	ConjuntoIntTDA c = new ConjuntoIntImpl();
    	ConjuntoIntTDA auxfechas = new ConjuntoIntImpl();
    	ConjuntoStringTDA auxeventos = new ConjuntoStringImpl();
    	int fecha;
    	if( a != null ){
    		c.InicializarConjunto();
    		auxfechas.InicializarConjunto();
    		auxfechas = a.FechasAgendadas();

    		while( !auxfechas.ConjuntoVacio()){
    			fecha = auxfechas.Elegir();
        		//auxeventos.InicializarConjunto();
        		auxeventos = a.EventosFecha(fecha);
        		//AKA TAMBIEN PREGUNTABA SI EXISTE LA FECHA ANTES DE ELIMINAR, NO HACE FALTA.. YA QUE ELIMINAR SI NO EXISTE NO HACE NADA!
    			c.Agregar(fecha);
    			auxfechas.Sacar(fecha);
    		}
    		return c;
    	}else{
    		return null;
    	}
    }
    
    
    
    /* Metodo que cuenta los eventos dados para una fecha
     * 
     */
    private static int CuentaEventos(ConjuntoStringTDA e){
    	int cont=0;
    	while(!e.ConjuntoVacio()){
    		e.Sacar(e.Elegir());
    		cont++;
    	}
    	return cont;
    }
    /*DiaConMasEventos: dada una agenda inicializada, determinar cual es el
     * dia con mas eventos agendados.
     * Como pueden existir varios dias con cantidad maxima de eventos
     * devuelve ConjuntoIntTDA
     */
    
    public static ConjuntoIntTDA DiaConMasEventos(AgendaTDA a){
    
    	//conjunto dias con mas eventos
    	ConjuntoIntTDA dias=new ConjuntoIntImpl();
    	dias.InicializarConjunto();
    	//conjunto fechas agendadas
    	ConjuntoIntTDA fechas=new ConjuntoIntImpl();
    	fechas.InicializarConjunto();
    	ConjuntoStringTDA eventos=new ConjuntoStringImpl();
    	eventos.InicializarConjunto();
    	
    	int fecha=0, numeventos=0, eventosmax=0;
    	fechas=a.FechasAgendadas();
    	
    	//examino el conjunto
    	while(!fechas.ConjuntoVacio()){
    		//elige una fecha con eventos
    		fecha=fechas.Elegir();
    		//cuenta el numero de eventos
    		eventos=a.EventosFecha(fecha);
    		numeventos=CuentaEventos(eventos);
    		//agrega fecha si coincide con eventos maximos
    		if(numeventos==eventosmax){
    			dias.Agregar(fecha);
    		}
    		//agrega la nueva fecha con maximos eventos
    		else if(numeventos>eventosmax){
    			dias.InicializarConjunto();
    			dias.Agregar(fecha);
    			eventosmax=numeventos;
    		}
    		fechas.Sacar(fecha);
    	}
    	return dias;
    }
    
    
    /* EventosMasRepetitivo: dada una agenda incializada, determinar 
	   * el conjunto de Eventos m�s agendado.
	   * Ejemplo:
	   * fecha: 20100510 eventos:futbol, cine
		 fecha: 20100517 eventos:clase UADE, 
		 fecha: 20100522 eventos:tenis,dentista 
		 fecha: 20100526 eventos:clase UADE, clase ingles,  
		 fecha: 20100529 eventos:futbol,  
		 
		 Los eventos Mas repetitivos son {"clase Ingles","Clase UADE"}
	   */ 

	    public static ConjuntoStringTDA EventosMasRepetitivo(AgendaTDA a) {
	    	
	    	ConjuntoStringTDA c = new ConjuntoStringImpl();
	    	ConjuntoIntTDA fechas = new ConjuntoIntImpl();
	    	ConjuntoStringTDA eventosfecha = new ConjuntoStringImpl();
	    	ConjuntoStringTDA auxeventos = new ConjuntoStringImpl();
	    	DiccionarioSimpleTDA eventosrepe = new DiccionarioSimpleImpl();
	    	ColaPrioridadTDA eventosprio = new ColaPrioridadImpl();
	    	int fecha;
	    	int iteracion;
	    	int iteraux = 0;
	    	String evento;
	    	boolean continuar;

	    	if( a != null ){
		    	c.InicializarConjunto();
		    	fechas.InicializarConjunto();
	    		fechas = a.FechasAgendadas();
	    		eventosrepe.InicializarDiccionario();

	    		while( !fechas.ConjuntoVacio()){
	    			fecha = fechas.Elegir();
	        		eventosfecha.InicializarConjunto();
	        		eventosfecha = a.EventosFecha(fecha);
	        		while( !eventosfecha.ConjuntoVacio()){
        				evento = eventosfecha.Elegir();
        				eventosfecha.Sacar(evento);
        				if( eventosrepe == null ){
        					eventosrepe.Agregar(evento, 1);
	        			}else{
	        				auxeventos = eventosrepe.Claves();
	        				if( auxeventos.Pertenece(evento) ){// AKA NO HACE FALTA COMPROBAR SI ES QUE PERTENECE O NO PERO NO LO TOCO YA QUE TODO ESTE METODO HAY QUE CAMBIAR Y HACERLO CON RECURSION CREO.
	        					iteracion = eventosrepe.Recuperar(evento) + 1;
	        				}else{
	        					iteracion = 1;
	        				}
        					eventosrepe.Agregar(evento, iteracion);
	        			}
	        		}
	    			fechas.Sacar(fecha);
	    		}

	    		auxeventos.InicializarConjunto();
	    		auxeventos = eventosrepe.Claves();
	    		while( !auxeventos.ConjuntoVacio() ){
	    			evento = auxeventos.Elegir();
	    			iteracion = eventosrepe.Recuperar(evento);
	    			eventosprio.AcolarPrioridad(evento, iteracion);
	    			auxeventos.Sacar(evento);
	    		}

	    		iteracion = 0;
	    		continuar = true;
	    		while( !eventosprio.ColaVacia() && continuar ){
	    			if( iteracion == 0 ){
		    			iteracion = eventosprio.Prioridad();
		    			evento = eventosprio.Primero();
		    			c.Agregar(evento);
		    			eventosprio.Desacolar();
	    			}else{
		    			iteraux = eventosprio.Prioridad();
		    			if( iteracion == iteraux ){
			    			evento = eventosprio.Primero();
			    			c.Agregar(evento);
			    			eventosprio.Desacolar();
		    			}else{
		    				continuar = false;
		    			}
	    			} 
	    		}
	    		return c;
	    	}else{
	    		return null;
	    	}
	    
	    }
}